//package com.zkthink.ceres.file.storage;
//
//import cn.hutool.core.util.StrUtil;
//import com.aliyun.oss.OSS;
//import com.aliyun.oss.OSSClientBuilder;
//import com.aliyun.oss.model.*;
//import com.qcloud.cos.COSClient;
//import com.qcloud.cos.ClientConfig;
//import com.qcloud.cos.auth.BasicCOSCredentials;
//import com.qcloud.cos.auth.COSCredentials;
//import com.qcloud.cos.http.HttpProtocol;
//import com.qcloud.cos.model.UploadResult;
//import com.qcloud.cos.model.ciModel.auditing.*;
//import com.qcloud.cos.region.Region;
//import com.qcloud.cos.transfer.TransferManager;
//import com.qcloud.cos.transfer.Upload;
//import com.zkthink.base.R;
//import com.zkthink.ceres.file.domain.FileDeleteDO;
//import com.zkthink.ceres.file.dto.chunk.FileChunksMergeDTO;
//import com.zkthink.ceres.file.entity.File;
//import com.zkthink.ceres.file.properties.FileServerProperties;
//import com.zkthink.ceres.file.strategy.impl.AbstractFileChunkStrategy;
//import com.zkthink.ceres.file.strategy.impl.AbstractFileStrategy;
//import com.zkthink.context.BaseContextHandler;
//import com.zkthink.exception.TencentPicException;
//import com.zkthink.utils.StrPool;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.io.FileUtils;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.boot.context.properties.EnableConfigurationProperties;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.stereotype.Service;
//import org.springframework.web.multipart.MultipartFile;
//
//import java.io.FileInputStream;
//import java.io.IOException;
//import java.io.InputStream;
//import java.net.URLEncoder;
//import java.time.LocalDate;
//import java.time.format.DateTimeFormatter;
//import java.util.ArrayList;
//import java.util.Comparator;
//import java.util.List;
//import java.util.UUID;
//import java.util.concurrent.ExecutorService;
//import java.util.concurrent.Executors;
//
//import static com.zkthink.ceres.common.constant.BizConstant.SUPER_TENANT;
//import static com.zkthink.utils.DateUtils.DEFAULT_MONTH_FORMAT_SLASH;
//
///**
// * 腾讯云OSS
// *
// * @author ceres
// * @date 2019/08/09
// */
//@EnableConfigurationProperties(FileServerProperties.class)
//@Configuration
//@Slf4j
//@ConditionalOnProperty(name = "ceres.file.type", havingValue = "TENCENT")
//public class TencentOssAutoConfigure {
//
//    @Service
//    public class TencentServiceImpl extends AbstractFileStrategy {
//        @Override
//        protected void uploadFile(File file, MultipartFile multipartFile) throws Exception {
//            FileServerProperties.Tencent tencent = fileProperties.getTencent();
//            // 1 初始化用户身份信息(secretId, secretKey)
//            COSCredentials cred = new BasicCOSCredentials(tencent.getAccesskey(), tencent.getSecretKey());
//            // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
//            // clientConfig中包含了设置region, https(默认http), 超时, 代理等set方法, 使用可参见源码或者接口文档FAQ中说明
//            ClientConfig clientConfig = new ClientConfig(new Region(tencent.getRegionid()));
//            clientConfig.setHttpProtocol(HttpProtocol.https);
//            // 3 生成cos客户端
//            COSClient cosClient = new COSClient(cred, clientConfig);
//
//            ExecutorService threadPool = Executors.newFixedThreadPool(32);
//
//            int machineId = 1;//最大支持1-9个集群机器部署
//
//            int hashCodeV = UUID.randomUUID().toString().hashCode();
//
//            if (hashCodeV < 0) {//有可能是负数
//
//                hashCodeV = -hashCodeV;
//
//            }
//
//
//            //生成文件名
//            String fileName = StrUtil.join(StrPool.EMPTY, machineId + String.format("%015d", hashCodeV), StrPool.DOT, file.getExt());
//            //日期文件夹
//            String tenant = BaseContextHandler.getTenant();
//
//
//            if (StrUtil.isBlank(tenant)) {
//                tenant = SUPER_TENANT;
//            }
//
//            String relativePath = StrPool.SLASH + LocalDate.now().format(DateTimeFormatter.ofPattern(DEFAULT_MONTH_FORMAT_SLASH));
//            // web服务器存放的绝对路径
//            String relativeFileName = relativePath + StrPool.SLASH + fileName;
//
//
//            com.qcloud.cos.model.ObjectMetadata objectMetadata = new com.qcloud.cos.model.ObjectMetadata();
//            objectMetadata.setContentDisposition("inline;fileName=" + URLEncoder.encode(file.getSubmittedFileName(), "UTF-8"));
//            objectMetadata.setContentType(file.getContextType());
//
//            TransferManager transferManager = new TransferManager(cosClient, threadPool);
//            com.qcloud.cos.model.PutObjectRequest putObjectRequest = new com.qcloud.cos.model.PutObjectRequest(tencent.getBucketName(), relativeFileName, multipartFile.getInputStream(), objectMetadata);
//
////            com.qcloud.cos.model.PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
////            cosClient.shutdown();
//
//            Upload upload = transferManager.upload(putObjectRequest);
//            UploadResult uploadResult = upload.waitForUploadResult();
//
//
//            String url = tencent.getUriPrefix() + relativeFileName;
//            file.setUrl(StrUtil.replace(url, "\\\\", StrPool.SLASH));
//
//            file.setUrl(StrUtil.replace(url, "\\\\", StrPool.SLASH));
//            file.setFilename(fileName);
//            file.setRelativePath(relativePath);
//            file.setPath(uploadResult.getRequestId());
//            transferManager.shutdownNow(true);
//            cosClient.shutdown();
//            /**
//             * 图片或者视频审核
//             */
//            //1.创建任务请求对象
//            if (file.getDataType().eq("image")) {
//                COSClient client = new COSClient(cred, clientConfig);
//                ImageAuditingRequest request = new ImageAuditingRequest();
//                //2.添加请求参数 参数详情请见api接口文档
//                //2.1设置请求bucket
//                request.setBucketName(tencent.getBucketName());
//                //2.2设置审核类型
//                request.setDetectType("porn,terrorist,ads,politics");
//                //2.3设置bucket中的图片位置
//                request.setObjectKey(relativeFileName);
//                //3.调用接口,获取任务响应对象
//                ImageAuditingResponse response = null;
//                try {
//                    response = client.imageAuditing(request);
//                    System.out.println("图片审核结果:" + response.toString());
//                    AdsInfo adsInfo = response.getAdsInfo();
//                    PoliticsInfo politicsInfo = response.getPoliticsInfo();
//                    PornInfo pornInfo = response.getPornInfo();
//                    TerroristInfo terroristInfo = response.getTerroristInfo();
//                    if ("1".equals(adsInfo.getHitFlag()) || "1".equals(politicsInfo.getHitFlag()) || "1".equals(pornInfo.getHitFlag()) || "1".equals(terroristInfo.getHitFlag())) {
//                        file.setHitFlag("1");
//                        throw new TencentPicException("图片违规");
//                    } else {
//                        file.setHitFlag("0");
//                    }
//                } catch (Exception e) {
//                    file.setHitFlag("3");
//                    throw new TencentPicException("图片审核失败");
//                }
//
//                client.shutdown();
//
//            } else if (file.getDataType().eq("video")) {
//                COSClient client = new COSClient(cred, clientConfig);
//                VideoAuditingRequest request = new VideoAuditingRequest();
//                //2.添加请求参数 参数详情请见api接口文档https://cloud.tencent.com/document/product/436/57231
//                request.setBucketName(tencent.getBucketName());
//                request.getInput().setObject(relativeFileName);
//                request.getConf().setDetectType("Porn,Ads");
//                request.getConf().getSnapshot().setCount("10");
//                request.getConf().getSnapshot().setMode("Interval");
//                request.getConf().getSnapshot().setTimeInterval("10");
//                //3.调用接口,获取任务响应对象
//                try {
//                    VideoAuditingResponse response = client.createVideoAuditingJob(request);
//                    System.out.println("视频审核结果:" + response.toString());
//                    file.setHitFlag("2");
//                    file.setJobId(response.getJobsDetail().getJobId());
//                    client.shutdown();
//                } catch (Exception e) {
//                    file.setHitFlag("3");
//                }
//            }
//
//
//        }
//
//        /**
//         * 根据jobId，查询视频审核结果
//         *
//         * @param jobId
//         * @return
//         */
//        @Override
//        protected VideoAuditingResponse describeAuditingJob(String jobId) {
//
//            FileServerProperties.Tencent tencent = fileProperties.getTencent();
//            // 1 初始化用户身份信息(secretId, secretKey)
//            COSCredentials cred = new BasicCOSCredentials(tencent.getAccesskey(), tencent.getSecretKey());
//            // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
//            // clientConfig中包含了设置region, https(默认http), 超时, 代理等set方法, 使用可参见源码或者接口文档FAQ中说明
//            ClientConfig clientConfig = new ClientConfig(new Region(tencent.getRegionid()));
//            clientConfig.setHttpProtocol(HttpProtocol.https);
//            // 3 生成cos客户端
//
//            COSClient client = new COSClient(cred, clientConfig);
//            //1.创建任务请求对象
//            VideoAuditingRequest request = new VideoAuditingRequest();
//            //2.添加请求参数 参数详情请见api接口文档
//            request.setBucketName(tencent.getBucketName());
//            request.setJobId(jobId);
//            //3.调用接口,获取任务响应对象
//            VideoAuditingResponse response = null;
//            try {
//                response = client.describeAuditingJob(request);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            return response;
//        }
//
//        @Override
//        protected InputStream readFile(String url) throws Exception {
//            FileServerProperties.Ali ali = fileProperties.getAli();
//            OSS ossClient = new OSSClientBuilder().build(ali.getEndpoint(), ali.getAccessKeyId(),
//                    ali.getAccessKeySecret());
//            String bucketName = ali.getBucketName();
//            if (!ossClient.doesBucketExist(bucketName)) {
//                ossClient.createBucket(bucketName);
//            }
//            OSSObject ossObject = ossClient.getObject(bucketName, url);
//            //获取输入流
//            InputStream input = ossObject.getObjectContent();
//            return input;
//        }
//
//        @Override
//        protected void delete(List<FileDeleteDO> list, FileDeleteDO file) {
//            FileServerProperties.Ali ali = fileProperties.getAli();
//            String bucketName = ali.getBucketName();
//            OSS ossClient = new OSSClientBuilder().build(ali.getEndpoint(), ali.getAccessKeyId(),
//                    ali.getAccessKeySecret());
//            ossClient.deleteObject(bucketName, file.getRelativePath() + StrPool.SLASH + file.getFileName());
//            ossClient.shutdown();
//        }
//    }
//
//
//    @Service
//    public class AliChunkServiceImpl extends AbstractFileChunkStrategy {
//        @Override
//        protected void copyFile(File file) {
//            FileServerProperties.Ali ali = fileProperties.getAli();
//            String sourceBucketName = ali.getBucketName();
//            String destinationBucketName = ali.getBucketName();
//            OSS ossClient = new OSSClientBuilder().build(ali.getEndpoint(), ali.getAccessKeyId(),
//                    ali.getAccessKeySecret());
//
//            String sourceObjectName = file.getRelativePath() + StrPool.SLASH + file.getFilename();
//            String fileName = UUID.randomUUID().toString() + StrPool.DOT + file.getExt();
//            String destinationObjectName = file.getRelativePath() + StrPool.SLASH + fileName;
//            ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceObjectName);
//            // 获取被拷贝文件的大小。
//
//            // 获取被拷贝文件的大小。
//            long contentLength = objectMetadata.getContentLength();
//
//            // 设置分片大小为10MB。
//            long partSize = 1024 * 1024 * 10;
//
//            // 计算分片总数。
//            int partCount = (int) (contentLength / partSize);
//            if (contentLength % partSize != 0) {
//                partCount++;
//            }
//            log.info("total part count:{}", partCount);
//
//            ObjectMetadata metadata = new ObjectMetadata();
//            metadata.setContentDisposition("attachment;fileName=" + file.getSubmittedFileName());
//            metadata.setContentType(file.getContextType());
//            // 初始化拷贝任务。可以通过InitiateMultipartUploadRequest指定目标文件元信息。
//            InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationObjectName, metadata);
//            InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
//            String uploadId = initiateMultipartUploadResult.getUploadId();
//
//            // 分片拷贝。
//            List<PartETag> partETags = new ArrayList<>();
//            for (int i = 0; i < partCount; i++) {
//                // 计算每个分片的大小。
//                long skipBytes = partSize * i;
//                long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;
//
//                // 创建UploadPartCopyRequest。可以通过UploadPartCopyRequest指定限定条件。
//                UploadPartCopyRequest uploadPartCopyRequest =
//                        new UploadPartCopyRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName);
//                uploadPartCopyRequest.setUploadId(uploadId);
//                uploadPartCopyRequest.setPartSize(size);
//                uploadPartCopyRequest.setBeginIndex(skipBytes);
//                uploadPartCopyRequest.setPartNumber(i + 1);
//                UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);
//
//                // 将返回的分片ETag保存到partETags中。
//                partETags.add(uploadPartCopyResult.getPartETag());
//            }
//
//            // 提交分片拷贝任务。
//            CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
//                    destinationBucketName, destinationObjectName, uploadId, partETags);
//            ossClient.completeMultipartUpload(completeMultipartUploadRequest);
//
//            String url = new StringBuilder(ali.getUriPrefix())
//                    .append(file.getRelativePath())
//                    .append(StrPool.SLASH)
//                    .append(fileName)
//                    .toString();
//            file.setUrl(StringUtils.replace(url, "\\\\", StrPool.SLASH));
//            file.setFilename(fileName);
//
//            // 关闭OSSClient。
//            ossClient.shutdown();
//        }
//
//        @Override
//        protected R<File> merge(List<java.io.File> files, String path, String fileName, FileChunksMergeDTO info) throws IOException {
//            FileServerProperties.Ali ali = fileProperties.getAli();
//            String bucketName = ali.getBucketName();
//            OSS ossClient = new OSSClientBuilder().build(ali.getEndpoint(), ali.getAccessKeyId(),
//                    ali.getAccessKeySecret());
//
//            //日期文件夹
//            String relativePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));
//            // web服务器存放的绝对路径
//            String relativeFileName = relativePath + StrPool.SLASH + fileName;
//
//            ObjectMetadata metadata = new ObjectMetadata();
//            metadata.setContentDisposition("attachment;fileName=" + info.getSubmittedFileName());
//            metadata.setContentType(info.getContextType());
//            //步骤1：初始化一个分片上传事件。
//            InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, relativeFileName, metadata);
//            InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
//            // 返回uploadId，它是分片上传事件的唯一标识，您可以根据这个ID来发起相关的操作，如取消分片上传、查询分片上传等。
//            String uploadId = result.getUploadId();
//
//            // partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
//            List<PartETag> partETags = new ArrayList<PartETag>();
//            for (int i = 0; i < files.size(); i++) {
//                java.io.File file = files.get(i);
//                FileInputStream in = FileUtils.openInputStream(file);
//
//                UploadPartRequest uploadPartRequest = new UploadPartRequest();
//                uploadPartRequest.setBucketName(bucketName);
//                uploadPartRequest.setKey(relativeFileName);
//                uploadPartRequest.setUploadId(uploadId);
//                uploadPartRequest.setInputStream(in);
//                // 设置分片大小。除了最后一个分片没有大小限制，其他的分片最小为100KB。
//                uploadPartRequest.setPartSize(file.length());
//                // 设置分片号。每一个上传的分片都有一个分片号，取值范围是1~10000，如果超出这个范围，OSS将返回InvalidArgument的错误码。
//                uploadPartRequest.setPartNumber(i + 1);
//
//                // 每个分片不需要按顺序上传，甚至可以在不同客户端上传，OSS会按照分片号排序组成完整的文件。
//                UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
//
//                // 每次上传分片之后，OSS的返回结果会包含一个PartETag。PartETag将被保存到partETags中。
//                partETags.add(uploadPartResult.getPartETag());
//            }
//
//            /* 步骤3：完成分片上传。 */
//            // 排序。partETags必须按分片号升序排列。
//            partETags.sort(Comparator.comparingInt(PartETag::getPartNumber));
//
//            // 在执行该操作时，需要提供所有有效的partETags。OSS收到提交的partETags后，会逐一验证每个分片的有效性。当所有的数据分片验证通过后，OSS将把这些分片组合成一个完整的文件。
//            CompleteMultipartUploadRequest completeMultipartUploadRequest =
//                    new CompleteMultipartUploadRequest(bucketName, relativeFileName, uploadId, partETags);
//
//            CompleteMultipartUploadResult uploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
//
//            String url = new StringBuilder(ali.getUriPrefix())
//                    .append(relativePath)
//                    .append(StrPool.SLASH)
//                    .append(fileName)
//                    .toString();
//            File filePo = File.builder()
//                    .relativePath(relativePath)
//                    .group(uploadResult.getETag())
//                    .path(uploadResult.getRequestId())
//                    .url(StringUtils.replace(url, "\\\\", StrPool.SLASH))
//                    .build();
//
//            // 关闭OSSClient。
//            ossClient.shutdown();
//            return R.success(filePo);
//        }
//    }
//}
